/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#pragma once

#include "reference/SmallPtDefines.h"
#include "reference/SmallPtMath.h"

#include <math.h>
#include <stdlib.h>
#include <stdio.h>  

namespace REF
{

/**    
*/
struct Ray 
{ 
public:
    Vec o;
    Vec d; 
public:
    Ray() {};
    Ray(const Vec& o_, const Vec& d_) : o(o_), d(d_) {};
};

enum Refl_t { DIFF, SPEC, REFR };  // material types, used in radiance()

/**
*/
struct Sphere 
{
public:
    SPT_FLOAT radius;        // radius
    Vec position;            // position
    Vec emission;            // emission
    Vec color;               // color
    Refl_t refl;             // reflection type (DIFFuse, SPECular, REFRactive)

public:
    Sphere(SPT_FLOAT rad_, const Vec& p_, const Vec& e_, const Vec& c_, Refl_t refl_) : radius(rad_), position(p_), emission(e_), color(c_), refl(refl_) {}

    /**
        ray sphere intersection
        @param[in]    r    ray
        @return distance, 0 if nohit
    */
    inline SPT_FLOAT intersect( const Ray &r, bool bSelfIntersect ) const 
    { 
        // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0
        Vec op = position-(r.o); 
        SPT_FLOAT t;
        SPT_FLOAT eps=1e-3f;
        SPT_FLOAT b=op.dot(r.d);
        SPT_FLOAT det=b*b-op.dot(op)+radius*radius;

        if (det<0.0f) {
            // no intersection
            return 0.0f; 
        }
        else {
            det=sqrt(det);
        }

        t = b-det;
        if( t > eps ) {
            return t;
        }
        t = b+det;
        if( t > eps ) {
            return t;
        }

        return 0;
    }
};

}